﻿<?php 
if (!class_exists('smartic')) {
    exit;
}
class text extends smartic {
    // vars
    public $element;
    public $element_name;
    public $element_type;
    public $Dattrs;
    private $HTML_FORMAT = '<input type="text" %s/>';
    // constructor function
    function __construct($options_ara = FALSE) {
        // element type
        $this->element['type'] = $this->element_type = get_class($this);
        // get element options
        if (is_array($options_ara) and isset($options_ara[0])) {
            if ($options = get_Options($options_ara[0])) {
                // element name
                $this->element_name = isset($options['name']) ? $options['name'] : FALSE;
                // set other options
                $this->element = array_merge($this->element, $options);
            } else {
                // element name
                $this->element_name = $options_ara[0];
            }
        } else {
            $this->element_name = FALSE;
        }
        // if method post or get
        $this->method(isset($options['method']) ? $options['method'] : FALSE);
        // set element name and take ref from it
        $this->setName($this->element_name);
        // set value
        $this->setValue();
    }
    // validate the form on submit
    function __destruct() {
        // vaidate inputes
        if (isset($this->element['value'])) {
            // merge error messages
            if (isset($this->element['error-msgs'])) {
                $messages = array_merge(config::$messages, $this->element['error-msgs']);
            } else {
                $messages = config::$messages;
            }
            // required validation
            if (isset($this->element['required']) && $this->element['required'] && $this->element['value'] == '') {
                // required
                $this->addError($messages['required']);
            } else if ($this->element['value'] != '') {
                // string length validation
                if (isset($this->element['length'])) {
                    if (isset($this->element['length']['minlength']) and $this->element['length']['currentlength'] < $this->element['length']['minlength']) {
                        $this->addError($messages['minlength']);
                    } else if (isset($this->element['length']['maxlength']) and $this->element['length']['currentlength'] > $this->element['length']['maxlength']) {
                        $this->addError($messages['maxlength']);
                    }
                }
                // number range validation
                if (isset($this->element['range'])) {
                    $value = (float) $this->element['value'];
                    if ($value < $this->element['range']['from'] || $value > $this->element['range']['to']) {
                        $this->addError($messages['range']);
                    }
                }
                // regex validation
                if (isset($this->element['regex'])) {
                    foreach ($this->element['regex']['pattern'] as $key=>$val) {
                        if (!preg_match($this->element['regex']['pattern'][$key], $this->element['value'])) {
                            $this->addError($this->element['regex']['message'][$key]);
                        }
                    }
                }
                // compare validation
                if (isset($this->element['compare'])) {
                    // get the element that we will compare with
                    $compare_with_value = parent::getElements($this->element['compare']['with'].'->value');
                    // compare condition
                    switch ($this->element['compare']['cond']) {
                        case '=':
                            if (!strcasecmp($this->element['value'], $compare_with_value)) {
                                $this->addError($messages['compare-equal']);
                            }
                            break;
                        case '!=':
                            if (strcasecmp($this->element['value'], $compare_with_value)) {
                                $this->addError($messages['compare-notEqual']);
                            }
                            break;
                    }
                }
            }
        }
        // set default value
        if (isset($this->element['default-value']) and $this->element['value'] == '') {
            $rendertoHTML = isset($this->element['default-value-attr']) ? $this->element['default-value-attr'] : FALSE;
            $this->setValue($this->element['default-value'], $rendertoHTML);
        }
        // to render HTML data
        $this->HTML();
        // add element info to list of elements array
        parent::addNewElementToElements($this->element);
    }
    // method
    public function method($str_method = FALSE) {
        // if method post or get
        if ((self::$method) and !($str_method)) {
            $method_up_case = strtoupper(self::$method);
        } else {
            $method_up_case = ($str_method) ? strtoupper($str_method) : 'POST';
        }
        $method = (!in_array($method_up_case, array('POST', 'GET'))) ? 'POST' : $method_up_case;
        // add method to element
        $this->element['method'] = $method;
        return $this;
    }
    // if this element required or not
    public function required($boolean = TRUE) {
        $this->element['required'] = (boolean)$boolean;
        return $this;
    }
    // element value string length
    public function length($option1 = FALSE, $option2 = FALSE) {
        // check
        if (isset($option1)) {
            // get element options
            $options = get_Options($option1);
            if ($options) {
                // element minimum length
                $min = isset($options['minlength']) ? (int) $options['minlength'] : FALSE;
                // element maxmimum length
                $max = isset($options['maxlength']) ? (int) $options['maxlength'] : FALSE;
            } else if (is_int($option2)) {
                // element minimum length
                $min = (int) $option1;
                // element maxmimum length
                $max = (int) $option2;
            } else if (is_int($option1)) {
                // element maxmimum length
                $max = (int) $option1;
            } else {
                parent::debug('function length not a number for {'.$this->element_name.'}');
            }
        } else {
            parent::debug('function length not a number for {'.$this->element_name.'}');
        }
        // set length
        if ($min) {
            $this->element['length']['minlength'] = $min;
        }
        if ($max) {
            $this->element['length']['maxlength'] = $max;
            // attr maxlength
            $this->defaultHTML("[maxlength=$max]");
        }
        // check if minimum > maximum length
        if (isset($min) and isset($max) and $min >= $max) {
            parent::debug('Sorry minimum {'.$min.'} length is > maximum {'.$max.'} {'.$this->element_name.'}');
        }
        return $this;
    }
    // element value number range($from,$to)
    public function range($option1 = FALSE, $option2 = FALSE) {
        // check
        if (isset($option1)) {
            // get element options
            $options = get_Options($option1);
            // match the pattern [from=50][to=100]
            if ($options and isset($options['from']) and isset($options['to'])) {
                // element range from
                $from = (float) $options['from'];
                // element range to
                $to = (float) $options['to'];
            } else if ($option2) {
                // element range from
                $from = (float) $option1;
                // element range to
                $to = (float) $option2;
            }
        }
        // check
        if (!$from || !$to) {
            parent::debug('function range "from" and "to" are required {'.$this->element_name.'}');
        } else {
            // if range from > to
            if ($from >= $to) {
                parent::debug('function range "from" is > from "to" {'.$this->element_name.'}');
            }
            // set
            (is_int($from) || is_float($from)) ? $this->element['range']['from'] = $from : parent::debug('not a number "from" function range '.$this->element_name);
            (is_int($to) || is_float($to)) ? $this->element['range']['to'] = $to : parent::debug('not a number "to" function range '.$this->element_name);
        }
        return $this;
    }
    // element regular expression
    public function regex($pattern = FALSE, $message = FALSE) {
        if ($pattern) {
            // get element options
            $options = get_Options($pattern);
            if ($options) {
                // pattern
                if (isset($options['pattern'])) {
                    $pattern = $options['pattern'];
                }
                // error message
                if (isset($options['message'])) {
                    $message = $options['message'];
                }
            }
        } else {
            parent::debug('No pattern for this element');
        }
        // pattern from config file
        if (array_key_exists($pattern, config::$regex)) {
            $this->element['regex']['pattern'][] = config::$regex[$pattern];
        } else {
            // check pattern validity
            if (strpos($pattern, '/') !== FALSE and strrpos($pattern, '/') !== FALSE) {
                $this->element['regex']['pattern'][] = $pattern;
            } else {
                $this->element['regex']['pattern'][] = '/'.$pattern.'/';
            }
        }
        // error message
        if ($message) {
            $this->element['regex']['message'][] = $message;
        } else {
            $this->element['regex']['message'][] = config::$messages['regex'];
        }
        return $this;
    }
    // element default value if post value is empty
    public function defaultValue($option1 = FALSE, $option2 = FALSE) {
        // check
        if (isset($option1)) {
            // get element options
            $options = get_Options($option1);
            // element default value
            if ($options) {
                $defaultvalue = isset($options['value']) ? $options['value'] : FALSE;
                $setHTMLvalue = isset($options['attr']) ? $options['attr'] : FALSE;
            } else if ($option1 and $option2) {
                $defaultvalue = $option1;
                $setHTMLvalue = $option2;
            }
        }
        ($defaultvalue !== FALSE) ? $this->element['default-value'] = $defaultvalue : parent::debug('Missing argument 1 for default value '.$this->element_name);
        // set the value of HTML if empty
        if ($setHTMLvalue) {
            $this->element['default-value-attr'] = TRUE;
        }
        return $this;
    }
    // element compare with other element in the same type
    public function compare($option1 = FALSE, $option2 = FALSE) {
        // get element options
        $options = get_Options($option1);
        // element to compare with
        $with = isset($options) and isset($options['with']) ? $options['with'] : isset($option1) ? $option1 : parent::debug('Missing argument 1 for compare function {'.$this->element_name.'}');
        // condetion
        $cond = isset($options['cond']) ? $options['cond'] : isset($option2) ? $option2 : '=';
        // check if element exists or not
        if (array_key_exists($with, parent::getElements())) {
            $this->element['compare']['with'] = $with;
        } else {
            parent::debug('This element dosn\'t exists to comapre with "'.$with.'" "'.$this->element_name.'"');
        }
        // condetion
        $cond_types = array('=', '!=');
        if (in_array($cond, $cond_types)) {
            $this->element['compare']['cond'] = $cond;
        } else {
            parent::debug('This condition "'.$cond.'" dosn\'t exists inside compare function '.$this->element_name);
        }
        return $this;
    }
    // to set element attributes
    public function attr($attrs = FALSE) {
        // get attributes
        $HTMLATTR_arr = get_options($attrs);
        if ($attrs and $HTMLATTR_arr) {
            // user attributes
            if (isset($this->attrs['user-attrs'])) {
                $this->attrs['user-attrs'] = array_merge($this->attrs['user-attrs'], $HTMLATTR_arr);
            } else {
                $this->attrs['user-attrs'] = $HTMLATTR_arr;
            }
        } else {
            parent::debug('you have passed wrong attributes for HTML function attr '.$attrs);
        }
        return $this;
    }
    // to set custom message for the given element
    public function customMessage($Message = FALSE) {
        if ($Message) {
            // get all errors list to replace with
            $Message_arr = get_options($Message);
            if (is_array($Message) || $Message_arr) {
                $this->element['error-msgs'] = $Message_arr;
            } else {
                parent::debug('Custom message firt paramter array or ex : [range=your message].');
            }
        } else {
            parent::debug('you have passed wrong error custom message.');
        }
    }
    // set element name and take ref from it
    protected function setName($elementName = FALSE) {
        // random name if empty or null
        $elementName = ( empty($elementName) || $elementName === TRUE) ? 'random'.rand(0, 10000) : $elementName;
        // set element name
        $this->element['name'] = $this->element_name = $elementName;
        // attr Name & ID
        $this->defaultHTML("[name=$elementName][id=$elementName]");
        // check if element name already exists or not
        if (array_key_exists($elementName, parent::getElementInfo($this->element_type.'.elements'))) {
            //
            parent::debug('This element name "'.$elementName.'" already exists.');
        }
    }
    // set element value
    protected function setValue($set_value = FALSE, $attr = FALSE) {
        if (self::$submit_status) {
            // value
            if ($set_value) {
                $value = $set_value;
            } else {
                // asssign posted value
                $method = $this->element['method'];
                if (isset($GLOBALS['_'.$method][$this->element_name])) {
                    $value = $GLOBALS['_'.$method][$this->element_name];
                }
            }
            // set element value
            $value = $this->element['value'] = (isset($this->element['trim']) and $this->element['trim']) ? trim($value) : $value;
            // current element value length
            $this->element['length']['currentlength'] = mb_strlen($value, config::$encoding);
            // set HTML value attr
            if ($set_value == FALSE || $attr) {
                $this->defaultHTML("[value=$value]");
            }
        }
    }
    // default attributes
    protected function defaultHTML($options = FALSE) {
        $defaultHTMLATTR = get_options($options);
        if ($defaultHTMLATTR) {
            $this->Dattrs = is_array($this->Dattrs) ? array_merge($this->Dattrs, $defaultHTMLATTR) : $defaultHTMLATTR;
        } else {
            parent::debug('wrong properties for default HTML attr '.$options);
        }
    }
    // to render HTML
    protected function HTML() {
        // default attributes
        $attrs = $this->element['default-attrs'] = $this->Dattrs;
        // check if user added attributes ot not
        if (isset($this->attrs['user-attrs'])) {
            // user attributes
            $this->element['user-attrs'] = $this->attrs['user-attrs'];
            $attrs = array_merge($this->Dattrs, $this->attrs['user-attrs']);
        }
        // HTML
        $all_attrs = '';
        foreach ($attrs as $key=>$val) {
            if ($val != config::$DELETEsign) {
                // to delete this attribute
                $all_attrs .= $key.'="'.strtr($val, array('"'=>'\'')).'" ';
            }
        }
        $this->element['HTML'] = htmlspecialchars(sprintf($this->HTML_FORMAT, $all_attrs));
    }
}
?>
